<template>
    <div
        :style="{
            background: '#222',
            display: 'flex',
            'justify-content': 'center',
            'align-items': 'center',
            width: offerWidth + 'px',
            height: offerHeight + 'px'
        }"
    >
        <video
            id="remoteVideo"
            :style="{ width: width + 'px', height: height + 'px' }"
            @mousedown="mousedown"
            @mouseup="mouseup"
            @mousemove="mousemove"
            @mousewheel="mousewheel"
        ></video>
    </div>
</template>

<script>
import io from 'socket.io-client'
let socket
export default {
    data() {
        return {
            keyCode: [
                'a',
                'b',
                'c',
                'd',
                'e',
                'f',
                'g',
                'h',
                'i',
                'j',
                'k',
                'l',
                'm',
                'n',
                'o',
                'p',
                'q',
                'r',
                's',
                't',
                'u',
                'v',
                'w',
                'x',
                'y',
                'z'
            ],
            from: this.$route.query.from,
            to: this.$route.query.to,
            mark: this.$route.query.mark,
            offerWidth: this.$route.query.width,
            offerHeight: this.$route.query.height,
            width: this.$route.query.width,
            height: this.$route.query.height,
            communicating: false,
            peer: null,
            dataChannel: null,
            userId: '',
            answerWidth: 0,
            answerHeight: 0,
            signalingState: false,
            remoteCandidates: []
        }
    },
    created() {
        this.$loading({ text: '正在远程桌面，请稍后...' })
        window.ipcRenderer.on('resize', (event, width, height) => {
            this.offerWidth = width
            this.offerHeight = height
            let radio = this.answerWidth / this.answerHeight
            let realityWidth = height * radio
            if (realityWidth <= this.offerWidth) {
                this.height = height
                this.width = realityWidth
            } else {
                this.width = this.offerWidth
                this.height = this.offerWidth / radio
            }
        })
        this.userId = this.from + '_' + this.to + '_' + this.mark
        socket = io.connect(window.platform.socketioUrl + '?userId=' + this.userId)
        socket.on('connect', () => {
            console.log('connected to server')
        })
        socket.on('disconnected', () => {
            console.log('disconnected with server')
        })
        socket.on('reconnect_error', error => {
            console.log('reconnect_error with server')
        })
        socket.on('acceptCall', async data => {
            this.answerWidth = data.width
            this.answerHeight = data.height
            // 计算video宽度高度
            let radio = this.answerWidth / this.answerHeight
            let realityWidth = this.offerHeight * radio
            if (realityWidth <= this.offerWidth) {
                this.height = this.offerHeight
                this.width = realityWidth
            } else {
                this.width = this.offerWidth
                this.height = this.offerWidth / radio
            }
            const iceConfiguration = {
                iceServers: [
                    { urls: 'stun:36.139.163.176:3478' },
                    {
                        urls: 'turn:36.139.163.176:3478',
                        username: 'authors',
                        credential: 'test110'
                    }
                ]
            }
            this.peer = new RTCPeerConnection(iceConfiguration)
            console.log('1、创建RTCPeerConnection')
            this.peer.onicecandidate = event => {
                if (event.candidate) {
                    console.log(event.candidate)
                    socket.emit('message', {
                        event: 'sendCandidateCaller',
                        candidate: event.candidate,
                        source: this.userId,
                        target: [this.to + '_' + this.from + '_' + this.mark]
                    })
                }
            }
            this.peer.onconnectionstatechange = () => {
                console.log(this.peer.connectionState)
                if (this.peer.connectionState === 'disconnected') {
                    if (this.peer) {
                        this.peer.close()
                        window.ipcRenderer.send('closeRemote')
                    }
                }
            }
            // 第一步:创建RTCPeerConnection
            // this.peer = new RTCPeerConnection()
            this.dataChannel = this.peer.createDataChannel('dataChannel')
            this.dataChannel.onopen = () => {
                this.communicating = true
            }
            this.peer.onaddstream = event => {
                let remoteVideo = document.getElementById('remoteVideo')
                remoteVideo.srcObject = event.stream
                remoteVideo.play()
                this.$loading().close()
            }
            // 第二步:发起连接createOffer(等到offer SDP)
            const offer = await this.peer.createOffer({
                offerToReceiveAudio: false,
                offerToReceiveVideo: true
            })
            console.log('2、发起连接createOffer(等到offer SDP)')
            // 第三步:setLocalDescription(设置offer SDP)
            await this.peer.setLocalDescription(offer)
            console.log('3、setLocalDescription(设置offer SDP)')
            socket.emit('message', {
                event: 'sendOffer',
                offer: offer,
                source: this.userId,
                target: [this.to + '_' + this.from + '_' + this.mark]
            })
        })
        socket.on('sendAnswer', async data => {
            this.peer.ondatachannel = event => {
                let receivedChannel = event.channel
                receivedChannel.onmessage = event => {
                    if (event.data === 'close') {
                        window.removeEventListener('keydown', this.handleKeyDown)
                        if (this.peer) {
                            this.peer.close()
                            window.ipcRenderer.send('closeRemote')
                        }
                    }
                }
            }
            await this.peer.setRemoteDescription(data.answer)
            console.log('9、setRemoteDescription(设置控制端answer SDP)')
            this.signalingState = true
            console.log('10、设置addIceCandidate Number:' + this.remoteCandidates.length)
            this.remoteCandidates.forEach(async candidate => {
                await this.peer.addIceCandidate(candidate)
            })
        })
        socket.on('sendCandidateCalled', async data => {
            if (this.signalingState) {
                console.log('10、设置addIceCandidate')
                await this.peer.addIceCandidate(data.candidate)
            } else {
                this.remoteCandidates.push(data.candidate)
            }
        })
    },
    async mounted() {
        window.ipcRenderer.on('close', () => {
            window.removeEventListener('keydown', this.handleKeyDown)
            if (this.peer) {
                this.dataChannel.send('close')
                this.peer.close()
            }
        })
        window.addEventListener('keydown', this.handleKeyDown)
        await this.callRemote()
    },
    beforeUnmount() {
        window.removeEventListener('keydown', this.handleKeyDown)
    },
    methods: {
        handleKeyDown(event) {
            event.preventDefault()
            let flag = event.ctrlKey || event.shiftKey || event.altKey || event.metaKey
            if (event.ctrlKey && event.key != 'Control') {
                this.dataChannel.send(
                    JSON.stringify({
                        type: 'keyboard',
                        action: 'tap',
                        key: event.key.toLowerCase(),
                        modifier: ['control']
                    })
                )
            } else if (event.shiftKey && event.key != 'Shift') {
                this.dataChannel.send(
                    JSON.stringify({
                        type: 'keyboard',
                        action: 'tap',
                        key: event.key.toLowerCase(),
                        modifier: ['shift']
                    })
                )
            } else if (event.altKey && event.key != 'Alt' && event.keyCode >= 65 && event.keyCode <= 90) {
                this.dataChannel.send(
                    JSON.stringify({
                        type: 'keyboard',
                        action: 'tap',
                        key: this.keyCode[event.keyCode - 65],
                        modifier: ['alt']
                    })
                )
            } else if (event.metaKey && event.key != 'Meta' && event.keyCode >= 65 && event.keyCode <= 90) {
                this.dataChannel.send(
                    JSON.stringify({
                        type: 'keyboard',
                        action: 'tap',
                        key: this.keyCode[event.keyCode - 65],
                        modifier: ['command']
                    })
                )
            } else if (!flag) {
                this.dataChannel.send(JSON.stringify({ type: 'keyboard', action: 'tap', key: event.key.toLowerCase() }))
            }
        },
        async callRemote() {
            socket.emit('message', {
                event: 'callRemote',
                source: this.from,
                target: [this.to],
                mark: this.mark
            })
        },
        acceptCall() {
            socket.emit('message', {
                event: 'acceptCall',
                width: this.width,
                height: this.height,
                source: this.userId,
                target: [this.to + '_' + this.from + '_' + this.mark]
            })
        },
        mousedown(event) {
            if (this.communicating) {
                if (event.button == 0) {
                    this.dataChannel.send(
                        JSON.stringify({ type: 'mouse', action: 'click', button: 'left', double: false })
                    )
                } else if (event.button == 1) {
                    this.dataChannel.send(
                        JSON.stringify({ type: 'mouse', action: 'click', button: 'middle', double: false })
                    )
                } else if (event.button == 2) {
                    this.dataChannel.send(
                        JSON.stringify({ type: 'mouse', action: 'click', button: 'right', double: false })
                    )
                }
            }
        },
        mousemove(event) {
            if (this.communicating) {
                let x = parseInt(event.offsetX * (this.answerWidth / this.width))
                let y = parseInt(event.offsetY * (this.answerHeight / this.height))
                this.dataChannel.send(JSON.stringify({ type: 'mouse', action: 'move', x: x, y: y }))
            }
        },
        mouseup(event) {
            // if (this.communicating) {
            //     if (event.button == 0) {
            //         this.dataChannel.send(
            //             JSON.stringify({ type: 'mouse', action: 'toggle', down: 'up', button: 'left' })
            //         )
            //     } else if (event.button == 1) {
            //         this.dataChannel.send(
            //             JSON.stringify({ type: 'mouse', action: 'toggle', down: 'up', button: 'middle' })
            //         )
            //     } else if (event.button == 2) {
            //         this.dataChannel.send(
            //             JSON.stringify({ type: 'mouse', action: 'toggle', down: 'up', button: 'right' })
            //         )
            //     }
            // }
        },
        mousewheel(event) {
            if (this.communicating) {
                if (event.wheelDelta || event.detail) {
                    if (event.wheelDelta > 0 || event.detail < 0) {
                        // 当鼠标滚轮向上滚动时
                        this.dataChannel.send(JSON.stringify({ type: 'mouse', action: 'scroll', x: 0, y: 10 }))
                    }
                    if (event.wheelDelta < 0 || event.detail > 0) {
                        // 当鼠标滚轮向下滚动时
                        this.dataChannel.send(JSON.stringify({ type: 'mouse', action: 'scroll', x: 0, y: -10 }))
                    }
                }
            }
        }
    }
}
</script>

<style scoped></style>
